#include "expressionvalidator_mt.h"

#include <bool.h>
#include <bstring.h>
#include <dynamictypemanager.h>
#include <expressionvalidator.h>
#include <number.h>
#include <typefactory.h>
#include <wfnet.h>

#include <QtTest/QTest>

using namespace wfnet;
using namespace moduletest;

void ExpressionValidator_mt::initTestCase()
{
    Bool boolean;
    BasicString string;
    Number number;

    m_net = new WfNet(this);

    DynamicTypeManager::getInstance()->registerColorSet(
        "Booleans", boolean, m_net);
    DynamicTypeManager::getInstance()->registerColorSet(
        "Strings", string, m_net);
    DynamicTypeManager::getInstance()->registerColorSet(
        "Numbers", number, m_net);
    DynamicTypeManager::getInstance()->registerColorSet(
        "NumbersTimed", number, m_net, true);

    DynamicTypeManager::getInstance()->registerVariable(
        "b", "Booleans", m_net);

    DynamicTypeManager::getInstance()->registerVariable(
        "s", "Strings", m_net);
    DynamicTypeManager::getInstance()->registerVariable(
        "t", "Strings", m_net);

    DynamicTypeManager::getInstance()->registerVariable(
        "n", "Numbers", m_net);
    DynamicTypeManager::getInstance()->registerVariable(
        "k", "Numbers", m_net);

    ExpressionValidator::getInstance()->registerKeywordMasks(
        TypeFactory::getInstance()->registeredKeywordMasks());
}

void ExpressionValidator_mt::validate()
{
    QFETCH(bool, value);
    QFETCH(bool, result);

    QCOMPARE(value, result);

    //QBENCHMARK {}
}

void ExpressionValidator_mt::validate_data()
{
    ExpressionValidator* validator = ExpressionValidator::getInstance();

    QTest::addColumn<bool>("value");
    QTest::addColumn<bool>("result");

    // valid
    QTest::newRow("b") << validator->validate("b", "Booleans", false, m_net) << true;
    QTest::newRow("s") << validator->validate("s", "Strings", false, m_net) << true;
    QTest::newRow("t") << validator->validate("t", "Strings", false, m_net) << true;
    QTest::newRow("n") << validator->validate("n", "Numbers", false, m_net) << true;
    QTest::newRow("k") << validator->validate("k", "Numbers", false, m_net) << true;
    QTest::newRow("1") << validator->validate("1", "Numbers", false, m_net) << true;

    QTest::newRow("b == true") << validator->validate("b == true", "Booleans",
        false, m_net) << true;
    QTest::newRow("b != false") << validator->validate("b != false", "Booleans",
        false, m_net) << true;

    QTest::newRow("s == t") << validator->validate("s == t", "Strings", false, m_net) <<
        true;
    QTest::newRow("s == \"string\"") <<
        validator->validate("s == \"string\"", "Strings", false, m_net) << true;

    QTest::newRow("n + 1") << validator->validate("n + 1", "Numbers", false, m_net) <<
        true;
    QTest::newRow("k + 1") << validator->validate("k + 1", "Numbers", false, m_net) <<
        true;
    QTest::newRow("(n + k)") << validator->validate("(n + k)", "Numbers",
        false, m_net) << true;
    QTest::newRow("(n + 1) + k") <<
        validator->validate("(n + 1) + k", "Numbers", false, m_net) << true;
    QTest::newRow("((n + 1) + k) + (n + (k - 5))") <<
        validator->validate("((n + 1) + k) + (n + (k - 5))", "Numbers", false, m_net) <<
            true;

    QTest::newRow("{2*\"PETRI\" + 1*\"NETS\"}") <<
        validator->validate("{2*\"PETRI\" + 1*\"NETS\"}", "Strings", false, m_net) <<
            true;
    QTest::newRow("{2*false + 1*true}") <<
        validator->validate("{2*false + 1*true}", "Booleans", false, m_net) << true;
    QTest::newRow("{2*10 + 1*5}") <<
        validator->validate("{2*10 + 1*5}", "Numbers", false, m_net) << true;
    QTest::newRow("({2*10 + 1*5})") <<
        validator->validate("({2*10 + 1*5})", "Numbers", false, m_net) << true;
    QTest::newRow("{2*s}") <<
        validator->validate("{2*s}", "Strings", false, m_net) << true;

    QTest::newRow("{2*s} * 2") <<
        validator->validate("{2*s} * 2", "Strings", false, m_net) << true;
    QTest::newRow("{2*t} <= {3*\"NETS\"}") <<
        validator->validate("{2*t} <= {3*\"NETS\"}", "Strings", false, m_net) << true;
    QTest::newRow("{2*b} + {1*true}") <<
        validator->validate("{2*b} + {1*true}", "Booleans", false, m_net) << true;
    QTest::newRow("{2*n}") <<
        validator->validate("{2*n}", "Numbers", false, m_net) << true;
    QTest::newRow("{2*n} + ({1*k})") <<
        validator->validate("{2*n} + ({1*k})", "Numbers", false, m_net) << true;
    QTest::newRow("{2*10 + 1*5} + {1*15}") <<
        validator->validate("{2*10 + 1*5} + {1*15}", "Numbers", false, m_net) << true;
    QTest::newRow("{2*10 + 1*5} + ({1*15})") <<
        validator->validate("{2*10 + 1*5} + ({1*15})", "Numbers", false, m_net) << true;
    QTest::newRow("{1*10@12}") <<
        validator->validate("{1*10@12}", "NumbersTimed", true, m_net) << true;
    QTest::newRow("{1*10@12} + {2*5@0}") <<
        validator->validate("{1*10@12} + {2*5@0}", "NumbersTimed", true, m_net) << true;

    // not valid
    QTest::newRow("") << validator->validate("", "Numbers", false, m_net) << false;
    QTest::newRow(" ") << validator->validate(" ", "Numbers", false, m_net) << false;
    QTest::newRow("+") << validator->validate("+", "Numbers", false, m_net) << false;
    QTest::newRow("n k") << validator->validate("n k", "Numbers", false, m_net) << false;
    QTest::newRow("n 1") << validator->validate("n 1", "Numbers", false, m_net) << false;
    QTest::newRow("n +") << validator->validate("n +", "Numbers", false, m_net) << false;
    QTest::newRow("n + + n") <<
        validator->validate("n + + n", "Numbers", false, m_net) << false;
    QTest::newRow("n + 1 n") <<
        validator->validate("n + 1 n", "Numbers", false, m_net) << false;
    QTest::newRow("+ n") << validator->validate("+ n", "Numbers", false, m_net) << false;
    QTest::newRow("x") << validator->validate("x", "Numbers", false, m_net) << false;
    QTest::newRow("(x") << validator->validate("(x", "Numbers", false, m_net) << false;
    QTest::newRow("x)") << validator->validate("x)", "Numbers", false, m_net) << false;
    QTest::newRow("x + true") <<
        validator->validate("x + true", "Booleans", false, m_net) << false;
    QTest::newRow("x + \"string\"") <<
        validator->validate("x + \"string\"", "Booleans", false, m_net) << false;

    QTest::newRow("s == n") <<
        validator->validate("s == n", "Booleans", false, m_net) << false;
    QTest::newRow("s == \"string\" + n") <<
        validator->validate("s == \"string\" + n", "Booleans", false, m_net) << false;
    QTest::newRow("(s == \"string\") + n") <<
        validator->validate("(s == \"string\") + n", "Booleans", false, m_net) << false;

    QTest::newRow("{2*10 + 1*5") <<
        validator->validate("{2*10 + 1*5", "Numbers", false, m_net) << false;
    QTest::newRow("2*10 + 1*5}") <<
        validator->validate("2*10 + 1*5}", "Numbers", false, m_net) << false;
    QTest::newRow("{(2*10) + 1*5}") <<
        validator->validate("{(2*10) + 1*5}", "Numbers", false, m_net) << false;
    QTest::newRow("{2*x}") <<
        validator->validate("{2*x}", "Numbers", false, m_net) << false;
    QTest::newRow("{2*10 1*5}") <<
        validator->validate("{2*10 1*5}", "Numbers", false, m_net) << false;
    QTest::newRow("{2*10 / 1*5}") <<
        validator->validate("{2*10 / 1*5}", "Numbers", false, m_net) << false;
    QTest::newRow("{10 + 1*5}") <<
        validator->validate("{10 + 1*5}", "Numbers", false, m_net) << false;
    QTest::newRow("{2*n + 1*10}") <<
        validator->validate("{2*n + 1*10}", "Numbers", false, m_net) << false;
    QTest::newRow("{1*n@12}") <<
        validator->validate("{1*n@12}", "NumbersTimed", true, m_net) << false;
    QTest::newRow("{1*10@12} + {2*5}") <<
        validator->validate("{1*10@12} + {2*5}", "NumbersTimed", true, m_net) << false;

    QTest::newRow("{1*10} + {1*true}") <<
        validator->validate("{1*10} + {1*true}", "Numbers", false, m_net) << false;
}

void ExpressionValidator_mt::cleanupTestCase()
{
    DynamicTypeManager::getInstance()->unregisterColorSet("Booleans",
        m_net);
    DynamicTypeManager::getInstance()->unregisterColorSet("Strings",
        m_net);
    DynamicTypeManager::getInstance()->unregisterColorSet("Numbers",
        m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("b", m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("s", m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("t", m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("n", m_net);
    DynamicTypeManager::getInstance()->unregisterVariable("k", m_net);

    ExpressionValidator::getInstance()->clearKeywordMasks();
}
